/**
 * FtpConnector.java
 * @author Daniel Liu
 * Create: 2006-12-22 ����07:14:28
 */
package lex.mtd.core.net;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Timer;
import java.util.TimerTask;

import org.lex.net.log.Log;
import org.lex.net.log.NullLog;
import org.lex.net.log.Log.Type;
import org.lex.utils.StateChangeSupport;


public class SunHttpConnector extends StateChangeSupport
{
	private int retryDelay = 5000;// ms
	private int maxRetryCount = 100;
	// =============================
	private Log log = null;
	private URL url = null;
	private URLConnection con = null;
	// =============================
	private Timer timer = null;
	private int retryCount = 0;
	private boolean cancel = false;

	public SunHttpConnector( Log log )
	{
		super();
		if( null == log )
			log = new NullLog();
		this.log = log;
	}

	public URLConnection getConnection()
	{
		return con;
	}

	public boolean isConnected()
	{
		return null != con;
	}

	public void connect( URL url )
	{
		this.url = url;
		this.cancel = false;
		this.retryCount = 0;
		this.timer = new Timer( true );
		this.timer.schedule( new Connector(), 0, retryDelay );
	}

	public void cancelRetry()
	{
		this.cancel = true;
		if( null != timer )
		{
			this.timer.cancel();
			this.timer = null;
		}
	}

	public void close()
	{
		this.cancelRetry();
		this.con = null;
	}

	public int getRetryCount()
	{
		return this.retryCount;
	}

	class Connector extends TimerTask
	{
		@Override
		public void run()
		{
			// check if reconnect was cancelled
			if( true == cancel )
			{
				log.error( url, "Reconnect attempt was cancelled" );
				cancelRetry();
				fireStateChanged( SunHttpConnector.this );
				return;
			}
			try
			{
				con = tryToConnect( url );
				cancelRetry();
				fireStateChanged( SunHttpConnector.this );
				return;
			}
			catch( IOException e )
			{
				log.error( url, e.getMessage() );
				// not connected, wait for (#retryDelay) to reconnect
				retryCount++;
				// check if reach the max-retry-count
				if( retryCount > maxRetryCount )
				{
					log.error( url, "Reach the maximum reconnect count and abort" );
					cancelRetry();
					fireStateChanged( SunHttpConnector.this );
					return;
				}
				log.misc( url, "Delaying for " + (retryDelay / 1000L)
						+ " seconds before reconnect attempt #" + retryCount );
			}
		}

		private URLConnection tryToConnect( URL url ) throws IOException
		{
			log.misc( url, "Connecting " + url.getHost() + "..." );
			URLConnection con = url.openConnection();
			HttpUtils.setRequests( con );
			HttpUtils.log( log, url, Type.SEND, con.getRequestProperties() );
			HttpUtils.log( log, url, Type.REPLY, con.getHeaderFields() );
			return con;
		}
	}
}
